package com.bolt.report.business.modules.report.controller;

import com.bolt.common.utils.StrUtil;
import com.bolt.common.web.RequestUtil;
import com.bolt.convention.data.*;
import com.bolt.convention.data.code.SuccessCode;
import com.bolt.report.business.ReportDBDefManager;
import com.bolt.report.business.modules.dataset.dto.converter.ReportDataSetConverter;
import com.bolt.report.business.modules.dataset.entity.ReportDataSetEntity;
import com.bolt.report.business.modules.dataset.service.ReportDataSetService;
import com.bolt.report.business.modules.param.dto.ReportDbParamDTO;
import com.bolt.report.business.modules.param.service.ReportDbParamService;
import com.bolt.report.business.modules.report.dto.ReportDTO;
import com.bolt.report.business.modules.report.dto.ReportQueryCriteria;
import com.bolt.report.business.modules.report.dto.converter.ReportConverter;
import com.bolt.report.business.modules.report.entity.ReportEntity;
import com.bolt.report.business.modules.report.service.ReportService;
import com.bolt.report.definition.DataSetDefinition;
import com.bolt.report.engine.ObjectFactory;
import com.bolt.report.engine.ReportConstants;
import com.bolt.report.engine.ReportDefManager;
import com.bolt.report.engine.fill.FillDataSet;
import com.bolt.report.exception.ReportException;
import com.bolt.report.util.GoogleBarCodeUtil;
import com.bolt.support.spring.jpa.specification.QueryHelp;
import freemarker.template.Configuration;
import freemarker.template.Template;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;

/**
 * Auto Generate Javadoc
 *
 * @author 日期:2021-11-22 17:47:51
 *         在线excel设计器
 **/
@RestController
@RequestMapping("report/design")
@RequiredArgsConstructor
@Api(tags = "在线excel设计器")
public class ReportController {

    private final ReportService reportService;

    private final ReportDataSetService reportDataSetService;

    private final ReportDbParamService reportDbParamService;

    @Resource(name = "dbReportDefManager")
    private ReportDefManager reportManager;

    @Resource(name = "reportFreeMarkerConfig")
    private Configuration cfg;

    @RequestMapping({"/index"})
    public void view(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String reportId = request.getParameter(ReportConstants.REPORT_ID_PARAM);
        if (StrUtil.isBlank(reportId)) {
            throw new ReportException("报表文件不存在");
        }
        try {
            response.setContentType("text/html;charset=UTF-8");
            PrintWriter output = response.getWriter();
            Map<String, Object> dataParam = new HashMap<>();
            dataParam.put("base", RequestUtil.getBaseUrl(request));
            dataParam.put(ReportConstants.REPORT_ID_PARAM, reportId);
            Template template = cfg.getTemplate(ReportConstants.REPORT_DESIGN_TEMPLATE_NAME);
            template.process(dataParam, output);
        } catch (Exception ex) {
            // logger.error(ex);
        }
    }

    /**
     * 在线excel设计器列表分页
     *
     * @return
     */
    @GetMapping(value = "/page")
    @ApiOperation(notes = "在线excel设计器列表分页", httpMethod = "GET", value = "在线excel设计器列表分页")
    public ResultMessage<PageInfo<ReportDTO>> page(Pageable pageable, ReportQueryCriteria queryCriteria) {
        PageInfo<ReportEntity> pageInfo = reportService.findPage(pageable, (root, criteriaQuery, criteriaBuilder)
                -> QueryHelp.getPredicate(root, queryCriteria, criteriaBuilder));
        return Results.success(pageInfo.map(K -> ReportConverter.toDTO(K)));
    }

    /**
     * 根据ID在线excel设计器操作
     */
    @GetMapping("/get/{id}")
    @ApiOperation(notes = "根据ID查询在线excel设计器", httpMethod = "GET", value = "根据ID查询在线excel设计器")
    public ResultMessage<ReportDTO> get(@PathVariable String id) {
        ReportEntity reportEntity = reportService.findOne(id).get();
        return Results.success(ReportConverter.toDTO(reportEntity));
    }


    /**
     * 在线excel设计器新增操作
     *
     * @param dao 表单数据
     * @return
     */
    @PostMapping
    @ApiOperation(notes = "在线excel设计器新增", httpMethod = "POST", value = "在线excel设计器新增")
    public ResultMessage<Void> save(@Validated @RequestBody ReportDTO dao) {
        reportService.add(dao);
        return Results.success();
    }

    @PutMapping
    @ApiOperation(notes = "在线excel设计器新增", httpMethod = "POST", value = "在线excel设计器新增")
    public ResultMessage<Void> edit(@Validated @RequestBody ReportDTO dao) {
        ReportEntity reportEntity = reportService.update(dao);
        if (null != reportManager) {
            reportManager.removeCache(reportEntity.getId());
        }
        return Results.success();
    }

    @PostMapping("/saveReportDataSet")
    @ApiOperation(notes = "在线excel设计器新增", httpMethod = "POST", value = "在线excel设计器新增")
    public ResultMessage<ReportDTO> saveReportDataSet(@Validated @RequestBody ReportDTO dao) {
        ReportEntity reportEntity = reportService.saveReportDataSet(dao);
        return Results.success(ReportConverter.toDTO(reportEntity));
    }

    /**
     * 在线excel设计器删除操作
     */
    @DeleteMapping
    @ApiOperation(notes = "根据ID删除在线excel设计器", httpMethod = "DELETE", value = "根据ID删除在线excel设计器")
    public ResultMessage<Void> doDelete(@RequestBody Set<String> ids) {
        for (String id : ids) {
            reportService.deleteById(id);
        }
        return Results.success();
    }


    @GetMapping("/runChart")
    @ApiOperation(notes = "运行图表数据预览", httpMethod = "GET", value = "运行图表数据预览")
    public ResultMessage refreshDataSet(HttpServletRequest request) {
        String dataSetId = request.getParameter(ReportConstants.REPORT_DATA_SET_ID);
        Map<String, Object> parameters = RequestUtil.getRequestMap(request);
        Optional<ReportDataSetEntity> definition = reportDataSetService.findOne(dataSetId);
        if (definition.isPresent()) {
            DataSetDefinition dataSetDefinition = ((ReportDBDefManager) reportManager).createDataSetDefinition(ReportDataSetConverter.toDTO(definition.get()));
            FillDataSet dataSet = ObjectFactory.createFillDataSet(dataSetDefinition, parameters);
            return Results.success(dataSet.initBindData().getRawData());
        } else {
            return Results.error("-1", "数据集不存在");
        }
    }

    @GetMapping("/createCode")
    @ApiOperation(notes = "生成条码", httpMethod = "GET", value = "生成条码")
    public ResultMessage<String> createCode(HttpServletRequest request) {
        Map<String, Object> parameters = RequestUtil.getRequestMap(request);
        String expr = (String) parameters.getOrDefault("expr", "boltReport");
        String type = (String) parameters.getOrDefault("type", "qrcode");
        String base64 = GoogleBarCodeUtil.createCode(expr, type, parameters);
        return new DefaultResultMessage<String>()
                .setCode(SuccessCode.SUCCESS.code())
                .setMessage(SuccessCode.SUCCESS.message()).setData(base64);
    }

    @GetMapping("/list")
    @ApiOperation(notes = "查询报表列表", httpMethod = "GET", value = "查询报表列表")
    public ResultMessage<List<Record>> findReportList() {
        List<Record> data = reportService.list();
        return Results.success(data);
    }
    @GetMapping("/getParam/{reportId}")
    @ApiOperation(notes = "查询报表参数", httpMethod = "GET", value = "查询报表参数")
    public ResultMessage<Set<ReportDbParamDTO>> getParam(@PathVariable String reportId) {
        Set<ReportDbParamDTO> data = reportDbParamService.findReportParam(reportId);
        return Results.success(data);
    }


}